package seismosurfer.gui.panel;

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.Point;
import java.io.Serializable;

import javax.swing.AbstractListModel;
import javax.swing.BoxLayout;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.ListCellRenderer;
import javax.swing.ListModel;
import javax.swing.UIManager;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.JTableHeader;

import seismosurfer.data.constants.ColumnNames;

import com.bbn.openmap.MapBean;
import com.bbn.openmap.MapHandler;
import com.bbn.openmap.gui.OMComponentPanel;
import com.bbn.openmap.gui.WindowSupport;
import com.bbn.openmap.util.Debug;

/**
 * The base class for showing the values of the attributes of
 * a map object on a dialog box, which is extended for specific
 * layers.
 *
 */
public abstract class AttributesPanel extends OMComponentPanel implements
        Serializable, ColumnNames {

    protected JTable masterTable;

    private String masterTableHeaders[] = {};

    protected Dimension dialogSize = new Dimension(400, 400);
    
    /**
     * Creates a dialog box which contains a panel
     * with the values of the attributes of
     * a map object.
     * 
     * @param name the name of the dialog box 
     */
    public AttributesPanel(String name) {
        this(name, true);
    }
    
    /**
     * Creates a dialog box which contains a panel
     * with the values of the attributes of
     * a map object.
     * 
     * @param name the name of the dialog box
     * @param createPanel true if you want to create the panel now
     */
    public AttributesPanel(String name, boolean createPanel) {

        super();
        setWindowSupport(new WindowSupport(this, name
                + " - selected feature attributes"));

        if (createPanel) {
            createPanel();
        }

    }
    
    /**
     * Sets the headers of the master table of the dialog box.
     * There may be a details table for a layer (e.g. earthquake
     * layer).
     * 
     * @param headers the headers of the table
     */
    public void setMasterTableHeaders(String[] headers) {
        masterTableHeaders = headers;
    }
    
    /**
     * Gets the headers of the master table of the
     * dialog box.
     * 
     * @return an array with the headers
     */
    public String[] getMasterTableHeaders() {
        return masterTableHeaders;
    }
    
    /**
     * Creates the panel where the values of
     * the attributes are shown.
     *
     */
    public void createPanel() {

        setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));

        JPanel centerPanel = new JPanel(new BorderLayout());        

        ListModel lm = new AbstractListModel() {            
            private static final long serialVersionUID = -8585732652033894056L;

            public int getSize() {
                return getMasterTableHeaders().length;
            }

            public Object getElementAt(int index) {
                return getMasterTableHeaders()[index];
            }
        };

        System.out.println("masterTableHeaders.length" + lm.getSize());

        DefaultTableModel dm = new DefaultTableModel(lm.getSize(), 1);
        masterTable = new JTable(dm);

        JList rowHeader = new JList(lm);
        rowHeader.setFixedCellWidth(150);
        rowHeader.setFixedCellHeight(masterTable.getRowHeight());

        rowHeader.setCellRenderer(new RowHeaderRenderer(masterTable));
        rowHeader.setBackground(masterTable.getTableHeader().getBackground());

        JScrollPane scroll = new JScrollPane(masterTable);
        scroll.setRowHeaderView(rowHeader);

        centerPanel.add(scroll);

        add(centerPanel);

        // We don`t want a column header
        masterTable.setTableHeader(null);

        validate();
    }
    
    /**
     * Sets the values of the attributes of a map object
     * at the master table cells.
     * 
     * @param data the data of a map object
     */
    public abstract void setAttributes(Object data);
    
    /**
     * Displays the dialog box.
     * 
     * @param point the point where the dialog box 
     *        will be displayed
     */
    public void showAttributesDialog(Point point) {

        MapHandler mh = (MapHandler) getBeanContext();
        Frame frame = null;
        if (mh != null) {
            frame = (Frame) mh.get(java.awt.Frame.class);

            if (frame == null) {
                MapBean mapBean = (MapBean) mh.get("com.bbn.openmap.MapBean");
                if (mapBean == null) {
                    Debug.message("layer",
                            "Layer.showPalette: Warning...mapBean = null");
                } else {
                    try {
                        java.awt.Component parent = mapBean.getParent();
                        while (parent.getParent() != null
                                && !(parent instanceof java.awt.Frame)) {
                            parent = parent.getParent();
                        }

                        if (parent instanceof java.awt.Frame) {
                            frame = (java.awt.Frame) parent;
                        }

                    } catch (Exception e) {
                        e.printStackTrace();
                    } // ignore any problems here
                }
            }
        }

        windowSupport.setComponentLocation(point);
        windowSupport.displayInWindow(frame, point.x, point.y,
                dialogSize.width, dialogSize.height);
    }

    public void setDialogSize(Dimension dim) {
        if (dim != null) {
            dialogSize = dim;
        }
    }

    public Dimension getDialogSize() {
        return dialogSize;
    }
    
    /**
     * This is used as a label for row and acts as the row
     * header.
     *
     */
    public class RowHeaderRenderer extends JLabel implements ListCellRenderer {
        
        private static final long serialVersionUID = 4047615453585670712L;

        RowHeaderRenderer(JTable table) {
            JTableHeader header = table.getTableHeader();
            setOpaque(true);
            setBorder(UIManager.getBorder("TableHeader.cellBorder"));
            setForeground(header.getForeground());
            setBackground(header.getBackground());
            setFont(header.getFont());
        }

        public Component getListCellRendererComponent(JList list, Object value,
                int index, boolean isSelected, boolean cellHasFocus) {
            setText((value == null) ? "" : value.toString());
            return this;
        }

    }
}
